package tum0r.data.serialize;

import com.alibaba.fastjson.JSONObject;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 工程: TestSerialize<br>
 * 包: tum0r.data.serialize<br>
 * 创建者: tum0r<br>
 * 创建时间: 2020/8/22 21:21<br>
 * <br>
 */
public class Serialize {
    private static String InstanceofBaseText = "InstanceofBaseAndIThinkThisNameIsTooLongAndWontRepeat";

    private static Object serializeBase(Object data) {
        Object result = null;
        LinkedList<Field> fields = Reflect.getFields(data, false);
        for (Field field : fields) {
            if (field.getName().equals("value")) {
                result = Reflect.getFieldValue(field, data);
            }
        }
        return result;
    }

    private static JSONObject serializeFunction(Object o, boolean justPublic) {
        JSONObject result = new JSONObject();
        if (o != null) {
            if (o instanceof Byte || o instanceof Short || o instanceof Integer || o instanceof Long ||
                    o instanceof Float || o instanceof Double || o instanceof Character || o instanceof Boolean) {
                result.put("value", serializeBase(o));
                result.put(InstanceofBaseText, true);
            } else if (o instanceof String || o instanceof Date) {
                result.put("value", o);
                result.put(InstanceofBaseText, true);
            } else if (o instanceof List || o instanceof Set) {
                Iterator<Object> iterator;
                if (o instanceof List) {
                    iterator = ((List) o).iterator();
                } else {
                    iterator = ((Set) o).iterator();
                }
                int index = 0;
                while (iterator.hasNext()) {
                    JSONObject temp = serializeFunction(iterator.next(), justPublic);
                    result.put(String.valueOf(index++), (boolean) temp.getOrDefault(InstanceofBaseText, false) ? temp.getOrDefault("value", null) : temp);
                }

            } else if (o instanceof Map) {
                Map map = ((Map) o);
                Iterator<Object> iterator = map.keySet().iterator();
                while (iterator.hasNext()) {
                    Object key = iterator.next();
                    JSONObject temp = serializeFunction(map.getOrDefault(key, null), justPublic);
                    result.put(key.toString(), (boolean) temp.getOrDefault(InstanceofBaseText, false) ? temp.getOrDefault("value", null) : temp);
                }
            } else {
                LinkedList<Field> fields = Reflect.getFields(o, justPublic);
                for (Field field : fields) {
                    JSONObject temp = serializeFunction(Reflect.getFieldValue(field, o), justPublic);
                    result.put(field.getName(), (boolean) temp.getOrDefault(InstanceofBaseText, false) ? temp.getOrDefault("value", null) : temp);
                }
            }
        }
        return result;
    }

    private static JSONObject fluentRemove(JSONObject data) {
        data = data.fluentRemove(InstanceofBaseText);
        for (String key : data.keySet()) {
            try {
                JSONObject temp = data.getJSONObject(key);
                if (temp != null && temp.size() != 0) {
                    temp = fluentRemove(temp);
                    data.replace(key, temp);
                }
            } catch (Exception ignored) {
            }
        }
        return data;
    }

    public static Object serialize(Object o, boolean justPublic) {
        JSONObject result = serializeFunction(o, justPublic);
        result = fluentRemove(result);
        if (result.size() == 1 && result.containsKey("value")) {
            return result.get("value");
        }
        return result;
    }

    public static Object serialize(Object o) {
        return serialize(o, true);
    }
}
